home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / MorphOS / Epic4_mos / share / epic / script / tabkey.ce < prev    next >
Encoding:
Text File  |  2002-10-28  |  5.9 KB  |  174 lines

  1. #
  2. # OK, here's the plan:
  3. #
  4. # Tabkey cuts the input line up into edible chunks, and selects a function
  5. # to do the actual completion.  The function will receive a single word as
  6. # its argument, and return a list of potential matches.  The word is whatever
  7. # is under the cursor, up to the insertion point at the current time.  The
  8. # word may be empty and the function should be able to cope with this.
  9. #
  10. # The exact function chosen works like this:
  11. # * If the current _word_ is a command (first word, begins with $cmdchars),
  12. #   call command_completion by way of parsekey (don't call any aliases).
  13. # * Or, if the current line is a command, it gets handed to $tabkey.cmd().
  14. # * Otherwise, call tabkey.default, which is a stub that can be changed
  15. #   to suit your preferences.  The default tabkey.default calls
  16. #   tabkey.nickchan which matches against all channels you're currently on
  17. #   and either the nicks in your current channel, or failing that, the
  18. #   nicks in all channels.
  19. # * tabkey.default is also called if tabkey.cmd() returns nothing.  If
  20. #   necessary, the function can prevent this behaviour by returning a single
  21. #   space, but this is discouraged.
  22. # * tabkey.default is also called by $tabkey.cmd() if it cannot find an
  23. #   appropriate command handler.
  24. # * $tabkey.cmd() will search for an appropriate function by joining the
  25. #   command and all its arguments together with dots and progressively
  26. #   removing those arguments until a function is found.
  27. #
  28. # tabkey "exports" a number of local variables that the functions may use
  29. #   or alter after using "bless":
  30. # * $curword is what tabkey believes the current word is.  The function
  31. #   may make use of this for context sensitivity.  I say believes because
  32. #   this may be open to different interpretations.
  33. # * $wordind is the character index of the _beginning_ of the word that is
  34. #   being completed.  If it is equal to $curpos(), then the first argument
  35. #   will be empty and the user has hit tab at the beginning of the word or
  36. #   in between words and the function should return all possible matches.
  37. #   The reason you may need to use it is if the function is designed to
  38. #   complete something that is not a single word.  It, and the current
  39. #   cursor position may be altered to cause tabkey to replace the chosen
  40. #   part of the string instead of just the word.
  41. #
  42. # The organisation of the supporting functions goes like this:
  43. # * "Context sensitive" functions are to be named with "tabkey.cmd." as a
  44. #   prefix followed by the name of the command that they are used to
  45. #   complete.  This is where tabkey.cmd will look for them.
  46. # * Generally, completion "methods" should be placed under tabkey.method
  47. #   and shouldn't rely on the exported variables being available, as user
  48. #   supplied functions may forget to re-export them.  Context sensitive
  49. #   functions should be as simple as possible.
  50. #
  51.  
  52. package tabkey.ce
  53. bind ^i parse_command tabkey
  54. alias tabkey.default tabkey.method.nickchan
  55.  
  56. alias tabkey {
  57.     @ :curword = indextoword($curpos() $L )
  58.     @ :wordind = wordtoindex($curword $L)
  59.     if (32 >= (127 & ascii($mid(${curpos()-1} 1 $L )))) {
  60.         @ curword++
  61.         @ wordind = curpos()
  62.     }
  63.     @ :word = mid($wordind ${curpos()-wordind} $L)
  64.     @ :matches = []
  65.     if (!index($cmdchars $L)) {
  66.         wait for @ matches = tabkey.cmd($word)
  67.     } else {
  68.         wait for @ :matches = tabkey.default($word)
  69.     }
  70.     @ :prefix = prefix($matches)
  71.     if (1 < numwords($matches) && word == prefix) {
  72.         echo Completions for \"$word\": $matches
  73.     } elsif (#matches && strlen($word) <= strlen($prefix)) {
  74.         repeat ${curpos()-wordind} parsekey backspace
  75.         xtype -l $prefix${1<#matches?:[ ]}
  76.     }
  77. }
  78.  
  79. alias tabkey.cmd {
  80.     bless
  81.     @ :ret = :cmd = []
  82.     @ :pass = chr($jot($ascii(AZ)))
  83.     @ :pass#= chr($jot($ascii(az)))
  84.     @ :pass#= chr($jot($ascii(09)))
  85.     @ :args = mid(0 $curpos() $L)
  86.     @ :args = unsplit(. $args)
  87.     @ :args = pass(._$pass $args)
  88.     if (!curword) {
  89.         @ ret = tabkey.method.commands($args)
  90.         repeat $#ret {push ret /$shift(ret)}
  91.         return $ret
  92.     }
  93.     while (args) {
  94.         @ :matches = aliasctl(alias pmatch tabkey.cmd.$args*)
  95.         @ :matches = prefix($matches)
  96.         if (aliasctl(alias exists $matches) && matches == [tabkey.cmd.$args]) {
  97.             @ args = matches
  98.             break
  99.         }
  100.         @ args = before(-1 . $args)
  101.     }
  102.     if (args) {
  103.         wait for @ ret = ${args}($*)
  104.     }
  105.     unless (strlen($ret)) {
  106.         wait for @ ret = tabkey.default($*)
  107.     }
  108.     return $ret
  109. }
  110.  
  111. # Context sensitive completion goes here.
  112.  
  113. alias tabkey.cmd.dcc {return $pattern("$0*" CHAT CLOSE CLOSEALL GET LIST RAW RENAME RESUME SEND)}
  114. alias tabkey.cmd.dcc.resume tabkey.cmd.dcc.send
  115. alias tabkey.cmd.dcc.send {
  116.     bless
  117.     switch ($curword) {
  118.         (0) {echo This should never happen.;call}
  119.         (1) {echo This should never happen.;call}
  120.         (2) {return $tabkey.method.nick($*)}
  121.         (*) {return $tabkey.method.filei($*)}
  122.     }
  123. }
  124.  
  125. alias tabkey.cmd.help {
  126.     bless
  127.     @ :matches = []
  128.     @ :path = restw(1 $left($curpos() $L))
  129.     if (wordind == curpos()) {@ push(path *)}
  130.     @ matches = globi($unsplit(/ $getset(HELP_PATH) $path*))
  131.     repeat $#matches @ push(matches $rightw(1 $remws(/ $split(/ $shift(matches)))))
  132.     return $matches
  133. }
  134.  
  135. # Methods.
  136.  
  137. alias tabkey.method.commands {
  138.     @ :ret = sort($uniq($getcommands($**) $aliasctl(alias match $*) $aliasctl(alias match $**)))
  139.     return $ret
  140. }
  141.  
  142. alias tabkey.method.chan { return $pattern("$0*" $mychannels()); }
  143. alias tabkey.method.notify { return $pattern("$0*" $notify(on)); }
  144.  
  145. alias alias.foo alias $*;alias $sar(g/globi/glob/$sar(g/filei/file/$*))
  146. alias.foo tabkey.method.filei {
  147.     @ :f0 = :f1 = globi("$0*")
  148.     while (numwords($f0) == 1 && f0 =~ [*/]) {
  149.         @ f0 = globi($f0*)
  150.     }
  151.     return ${f0 ? f0 : f1}
  152. }
  153. alias -alias.foo
  154.  
  155. alias tabkey.method.nick {
  156.     if (pattern($0* $chanusers())) {
  157.         return $pattern($0* $chanusers());
  158.     } else {
  159.         @ :chanusers = []
  160.         fe ($mychannels()) chan {
  161.             @ push(chanusers $chanusers($chan))
  162.         }
  163.         return $pattern($0* $sort($uniq($chanusers)));
  164.     }
  165. }
  166.  
  167. alias tabkey.method.nickchan {
  168.     return $remws(/ $tabkey.method.chan($*) $tabkey.method.nick($*))
  169. }
  170.  
  171. alias tabkey.method.nickchannotify {
  172.     return $remws(/ $tabkey.method.chan($*) $sort($uniq($tabkey.method.nick($*) $tabkey.method.notify($*))))
  173. }
  174.